package interaction;


import interaction.input.AudioInputListener;
import interaction.input.AbstractComponent;
import interaction.input.Component;
import interaction.input.ComponentCollection;
import interaction.input.InputListener;

import interaction.audio.AudioProcessor;
import interaction.drawable.Drawable;
import interaction.drawable.DrawableCollection;

import java.util.LinkedList;
import java.util.List;

import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PGraphics;
import processing.core.PVector;

/**
 * A core applet window class that delegates setup, input handling and drawing
 * to external instances.
 */
public class App extends PApplet {
	private DrawableCollection drawables = new DrawableCollection();
	private List<InputListener> listeners = new LinkedList<InputListener>();
	private List<AudioInputListener> audioListeners = new LinkedList<AudioInputListener>();
	
	private AudioProcessor audio;
	
	public void setAudioController(AudioProcessor audio)
	{
		this.audio = audio;
	}
	
	public AudioProcessor getAudioController()
	{
		return audio;
	}
	
	public PVector getSizeVector()
	{
		return new PVector(width, height);
	}

	public App add(Component c)
	{
		addDrawable(c);
		addListener(c);
		addAudioListener(c);
		
		return this;
	}

	public App addDrawable(Drawable d)
	{
		drawables.add(d);
		return this;
	}

	public App addListener(InputListener l)
	{
		listeners.add(l);
		return this;
	}
	
	public App addAudioListener(AudioInputListener l)
	{
		audioListeners.add(l);
		return this;
	}

	public void setup()
	{
		new Bootstrap().init(this);
	}

	public void draw()
	{
		background(0);
		
		audio.process();
		if (audio.beatDetected()) {
			beatReceived();
		}
		
		PGraphics g = createGraphics();
		g.beginDraw();
		g.smooth();

		for (Drawable d : drawables) {
			d.draw(g);
		}

		g.endDraw();
		image(g, 0, 0);
	}
	
	public void beatReceived()
	{
		for (AudioInputListener l : audioListeners) {
			l.beatReceived(audio.getAudioSpectrumSample());
		}
	}

	public void keyPressed()
	{
		for (InputListener l : listeners) {
			l.keyPressed(key);
		}
	}

	public void mousePressed()
	{
		for (InputListener l : listeners) {
			l.mousePressed(new PVector(mouseX, mouseY));
		}
	}

	public void mouseMoved() {
		for (InputListener l : listeners) {
			l.mouseMoved(new PVector(mouseX, mouseY));
		}
	}

	public PGraphics createGraphics()
	{
		PGraphics g = createGraphics(width, height, P2D);
		g.smooth();
		return g;
	}
	
	public PFont createFont(float size, String ... fonts)
	{
		RuntimeException result = null;
		for (String f : fonts) {
			try {
				return super.createFont(f, size, true);
			} catch (RuntimeException e) {
				result = e;
			}
		}
		throw result;
	}
}
